#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include "imagem.h"

/* Dados valores para os canais de um pixel, determina se o mesmo deve ser
considerado como o laser */
inline short int verificar_pixel_laser(uchar b, uchar g, uchar r) {
    return (
        (r > 215) &&
        (g < 170) &&
        (b < 170)
    );
	/*return (
	    (abs(r - 130) < 5) &&
	    (abs(g - 130) < 5) &&
        (abs(b - 130) < 5)
	);*/
}

inline void ImagemAlterarContraste(Imagem* img, double contraste) {
	cvSetCaptureProperty(img->capture, CV_CAP_PROP_CONTRAST, contraste);    
}

inline void ImagemAlterarBrilho(Imagem* img, double brilho) {
	cvSetCaptureProperty(img->capture, CV_CAP_PROP_BRIGHTNESS, brilho);
}

inline double ImagemObterContraste(Imagem* img) {
    return cvGetCaptureProperty(img->capture, CV_CAP_PROP_CONTRAST);
}

inline double ImagemObterBrilho(Imagem* img) {
    return cvGetCaptureProperty(img->capture, CV_CAP_PROP_BRIGHTNESS);
}

/* Inicializar TAD Imagem */
void ImagemInicializar(Imagem* img) {
	img->deviceno = 0;
	(img->laser).x = (img->laser).y = -1;
	img->capture = NULL;
	img->frame = NULL;
}

/* Conectar com a Webcam */
short int ImagemConectar(Imagem* img, short int deviceno) {
	img->deviceno = deviceno;
	(img->laser).x = (img->laser).y = -1;
	if(img->capture)
		ImagemLiberar(img);
	img->capture = cvCreateCameraCapture(img->deviceno);
	cvSetCaptureProperty(img->capture, CV_CAP_PROP_FRAME_WIDTH, WIDTH);
	cvSetCaptureProperty(img->capture, CV_CAP_PROP_FRAME_HEIGHT, HEIGHT);
	//Tentando inicializar dispositivo
	img->frame = cvQueryFrame(img->capture);
	return ImagemVerificarConexao(img);
}

/* Verifica se existe uma conexaõ com a câmera escolhida */
short int ImagemVerificarConexao(Imagem *img) {
	if(img->capture)
		return 1;
	else
		return 0;
}

/* Liberar recursos reservados pela TAD Imagem */
void ImagemLiberar(Imagem* img) {
	cvReleaseCapture(&(img->capture));
	img->capture = NULL;
}

/* Cria uma janela nomeada para exibição do vídeo */
void ImagemAbrirJanela() {
	cvNamedWindow(JANELA, CV_WINDOW_AUTOSIZE);
}

/* Destrói uma janela nomeada para exibição de vídeo */
void ImagemFecharJanela() {
	cvDestroyWindow(JANELA);
}

/* Destaca o laser detectado */
void ImagemDestacarLaser(Imagem* img) {
	if( (img->laser).x != -1)
		cvCircle(
				img->frame, img->laser, 5,
				CV_RGB(80,0,0), CV_FILLED, 8, 0
		);
}

/* Exibe um quadro em uma janela nomeada */
void ImagemExibir(Imagem* img) {
	cvShowImage(JANELA, img->frame);
}

/* Captura um frame da câmera */
short int ImagemObterFrame(Imagem *img) {
	if(!cvGrabFrame(img->capture)) //erro na captura do frame
		return 0;
	img->frame = cvRetrieveFrame(img->capture);
	return 1;
}

/* Detectar laser em um quadro */
short int ImagemDetectarLaser(Imagem* img) {
	int x, y, posicao_pixel;
	short int laser_detectado = 0;
	IplImage *hsv = cvCreateImage(cvGetSize(img->frame), IPL_DEPTH_8U, 3);
	cvCvtColor(img->frame, hsv, CV_RGB2HSV);
	for(y=0; y < img->frame->height; y++) {
		uchar* ptr = (uchar*) (img->frame->imageData + y * img->frame->widthStep);
		for(x=0; x < img->frame->width; x += 2) {
			posicao_pixel = 3*x;
			laser_detectado = verificar_pixel_laser(
				ptr[posicao_pixel],
				ptr[posicao_pixel+1],
				ptr[posicao_pixel+2]
			);
			if(laser_detectado) {
				(img->laser).x = x;
				(img->laser).y = y;
				cvReleaseImage(&hsv);
				return 1;
			}
		}
	}
	(img->laser).x = (img->laser).y = -1;
	cvReleaseImage(&hsv);
	return 0;
}

IplImage *ImagemObterDados(Imagem* img) {
    return img->frame;
}

void ImagemObterCor(Imagem* imgrgb, Cor *rgb, Cor *hsv, int x, int y) {
    int posicao_pixel;
	IplImage *imghsv = cvCreateImage(cvGetSize(imgrgb->frame), IPL_DEPTH_8U, 3);
	cvCvtColor(imgrgb->frame, imghsv, CV_RGB2HSV);
    uchar* ptr_rgb = (uchar*) (imgrgb->frame->imageData + y * imgrgb->frame->widthStep);
    uchar* ptr_hsv = (uchar*) (imghsv->imageData + y * imghsv->widthStep);    
    posicao_pixel = 3*x;
    rgb->c1 = ptr_rgb[posicao_pixel];
    rgb->c2 = ptr_rgb[posicao_pixel+1];
    rgb->c3 = ptr_rgb[posicao_pixel+2];
    hsv->c1 = ptr_hsv[posicao_pixel];
    hsv->c2 = ptr_hsv[posicao_pixel+1];
    hsv->c3 = ptr_hsv[posicao_pixel+2];
	cvReleaseImage(&imghsv);
}

/* Salva a imagem em um arquivo */
void ImagemSalvar(Imagem* img, char* arquivo) {
	cvSaveImage(arquivo, img->frame);
}
